package com.syf.kit;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import com.syf.core.kit.SyFrameKit;
import com.syf.kit.config.SyIdGeneratorConfiguration;
import com.syf.kit.snowflake.BRStyle;
import com.syf.kit.snowflake.SnowFlakeFactory;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

@SyFrameKit("id生成器")
public class SyIdGenerator {

    private static final AtomicLong startSeqNoLong = new AtomicLong(1000000000000001L);

    private static final AtomicInteger startSeqNoInt = new AtomicInteger(10000001);

    private SyIdGeneratorConfiguration configuration;

    private final SnowFlakeFactory snowFlakeFactory;

    public SyIdGenerator(SyIdGeneratorConfiguration configuration) {
        this.configuration = configuration;
        this.snowFlakeFactory = new SnowFlakeFactory(configuration.getIdcId(), configuration.getMachineId());
    }

    /**
     * 根据内存原子计数，获取进程内id，最长长度为16位
     */
    public String getUniqueSeqInCourse(int len) {
        if (len > 16) {
            len = 16;
        }

        long nextId = startSeqNoLong.addAndGet(1);
        return String.valueOf(nextId).substring(16 - len);
    }

    /**
     * 获取带时间戳的序号，生成策略: yyyyMMddHHmmssSSS + machineId(两位) + 3位seqNo
     */
    public String getSyStrategySeqNo() {
        StringBuilder sb = new StringBuilder();
        DateTime now = DateTime.now();
        sb.append(now.toString(DatePattern.PURE_DATETIME_MS_PATTERN));

        if (configuration.getMachineId() < 10L) {
            sb.append("0").append(configuration.getMachineId());
        } else {
            sb.append(configuration.getMachineId());
        }

        int nextId = startSeqNoInt.addAndGet(1);
        sb.append(String.valueOf(nextId).substring(5));

        return sb.toString();
    }

    /**
     * 获取雪花算法Id
     */
    public String getSnowFlackSeqNo() {
        return snowFlakeFactory.nextId(BRStyle.seqNo);
    }

    /**
     * 获取雪花算法TraceId
     */
    public String getSnowFlackTraceId() {
        return snowFlakeFactory.nextId(BRStyle.traceId);
    }
}
